

<!DOCTYPE html>
<html lang="en" color-mode=light>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>字节码增强（二） - Alex</title>
  <meta name="apple-mobile-web-app-capable" content="yes" />
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
  <meta name="google" content="notranslate" />
  
  <meta name="description" content="​    字节码增强（一）在理论上分析了插桩的方案，本...">
  <meta name="author" content="Alex">
  <link rel="icon" href="/images/icons/favicon-16x16.png" type="image/png" sizes="16x16">
  <link rel="icon" href="/images/icons/favicon-32x32.png" type="image/png" sizes="32x32">
  <link rel="apple-touch-icon" href="/images/icons/apple-touch-icon.png" sizes="180x180">
  <meta rel="mask-icon" href="/images/icons/stun-logo.svg" color="#333333">
  
    <meta rel="msapplication-TileImage" content="/images/icons/favicon-144x144.png">
    <meta rel="msapplication-TileColor" content="#000000">
  

  
<link rel="stylesheet" href="/css/style.css">


  
    
<link rel="stylesheet" href="//at.alicdn.com/t/font_1445822_s6x2xcokxrl.css">

  

  
    
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css">

  

  
    
      
        
        
<link rel="stylesheet" href="https://cdn.bootcss.com/highlight.js/9.18.1/styles/xcode.min.css" name="highlight-style" mode="light">

      
        
        
<link rel="stylesheet" href="https://cdn.bootcss.com/highlight.js/9.18.1/styles/solarized-dark.min.css" name="highlight-style" mode="dark">

      
  

  <script>
    var CONFIG = window.CONFIG || {};
    var ZHAOO = window.ZHAOO || {};
    CONFIG = {
      isHome: false,
      fancybox: true,
      pjax: false,
      lazyload: {
        enable: true,
        only_post: 'false',
        loading: '/images/theme/loading.gif'
      },
      donate: {
        enable: true,
        alipay: 'https://pic.izhaoo.com/alipay.jpg',
        wechat: 'https://pic.izhaoo.com/wechat.jpg'
      },
      galleries: {
        enable: true
      },
      fab: {
        enable: true,
        always_show: false
      },
      carrier: {
        enable: true
      },
      daovoice: {
        enable: false
      },
      preview: {
        background: {
          default: '/images/theme/welcome-image.jpg',
          api: ''
        },
        motto: {
          default: '我在开了灯的床头下，想问问自己的心啊。',
          api: 'https://v2.jinrishici.com/one.json',
          data_contents: '["data","content"]'
        },
      },
      qrcode: {
        enable: true,
        type: 'url',
        image: 'https://pic.izhaoo.com/weapp-code.jpg',
      },
      toc: {
        enable: true
      },
      scrollbar: {
        model: 'simple'
      },
      notification: {
        enable: false,
        delay: 4500,
        list: '',
        page_white_list: '',
        page_black_list: ''
      }
    }
  </script>

  

  

<meta name="generator" content="Hexo 5.1.1"></head>

<body class="lock-screen">
  <div class="loading"></div>
  


  <nav class="navbar">
    <div class="left">
      
        <i class="iconfont iconqrcode j-navbar-qrcode"></i>
      
      
        <i class="iconfont iconmoono" id="color-toggle" color-toggle="light"></i>
      
    </div>
    <div class="center">字节码增强（二）</div>
    <div class="right">
      <i class="iconfont iconmenu j-navbar-menu"></i>
    </div>
    
      <div id="qrcode-navbar"></div>
    
  </nav>

  

<nav class="menu">
  <div class="menu-wrap">
    <div class="menu-close">
      <i class="iconfont iconbaseline-close-px"></i>
    </div>
    <ul class="menu-content"><li class="menu-item">
        <a href="/ " class="underline "> 首页</a>
      </li><li class="menu-item">
        <a href="/galleries/ " class="underline "> 摄影</a>
      </li><li class="menu-item">
        <a href="/archives/ " class="underline "> 归档</a>
      </li><li class="menu-item">
        <a href="/tags/ " class="underline "> 标签</a>
      </li><li class="menu-item">
        <a href="/categories/ " class="underline "> 分类</a>
      </li><li class="menu-item">
        <a href="/about/ " class="underline "> 关于</a>
      </li></ul>
    
      <div class="menu-copyright"><p>Powered by <a target="_blank" href="https://hexo.io">Hexo</a>  |  Theme - <a target="_blank" href="https://github.com/izhaoo/hexo-theme-zhaoo">zhaoo</a></p></div>
    
  </div>
</nav>
  <main id="main">
  <div class="article-wrap">
    <div class="row container">
      <div class="col-xl-3"></div>
      <div class="col-xl-6"><article class="article">
  <div class="wrap">
    <section class="head">
  <img   class="lazyload" data-original="/images/theme/post-image.jpg" src=""  draggable="false">
  <div class="head-mask">
    <h1 class="head-title">字节码增强（二）</h1>
    <div class="head-info">
      <span class="post-info-item"><i class="iconfont iconcalendar"></i>September 26, 2020</span>
      
      <span class="post-info-item"><i class="iconfont iconfont-size"></i>5530</span>
    </div>
  </div>
</section>
    <section class="main">
      <section class="content">
        <blockquote>
<p><strong>增强目标：</strong>在每次使用<code>new</code>关键字创建实例后，调用提前写好的native函数，将实例的引用<code>o</code>、变量名<code>objName</code>、<code>new</code>的java代码行数<code>lineNumber</code>作为参数传入。</p>
<p>​    这个navtive函数长这个样子:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NativeC</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">native</span> <span class="hljs-keyword">void</span> <span class="hljs-title">newObj</span><span class="hljs-params">(Object o ,<span class="hljs-keyword">int</span> lineNumber,String objName)</span></span>;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">native</span> <span class="hljs-keyword">void</span> <span class="hljs-title">newArr</span><span class="hljs-params">(Object o ,<span class="hljs-keyword">int</span> lineNumber,String objName)</span></span>;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p><strong>需要处理的问题：</strong></p>
<ol>
<li>找到<code>new</code>关键字的位置及其在java代码中的行数</li>
<li>找到变量名</li>
<li>插入函数调用，调用native函数。</li>
</ol>
<p><strong>插桩方案</strong></p>
<ul>
<li>使用javassist工具，遍历方法中的字节码，找到创建实例的指令。</li>
<li>调整操作栈顶的数据，使得可以调用native函数</li>
<li>插入字节码指令。</li>
</ul>
</blockquote>
<h2 id="读取类文件"><a href="#读取类文件" class="headerlink" title="读取类文件"></a>读取类文件</h2><p>​    javassist库提供了<code>ClassFile</code>类，该类按照.class文件的结构进行了封装，只需将.class文件数据传入即可使用。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java">BufferedInputStream fin = <span class="hljs-keyword">new</span> BufferedInputStream(<span class="hljs-keyword">new</span> FileInputStream(inputClassFileName));<br><span class="hljs-comment">//inputClassFileName 即输入的.class文件的文件名</span><br>ClassFile classFile = <span class="hljs-keyword">new</span> ClassFile(<span class="hljs-keyword">new</span> DataInputStream(fin));<br><span class="hljs-comment">//ClassFile实例的创建与读文件差别不大。</span><br><span class="hljs-comment">//之后即可通过classFile对象来获取类文件中的信息。如版本号、类名、成员变量、方法、常量池等。</span><br></code></pre></td></tr></table></figure>

<h2 id="获取class的方法表"><a href="#获取class的方法表" class="headerlink" title="获取class的方法表"></a>获取class的方法表</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//MethodInfo 是javassist中的类，封装了类文件中的方法表。</span><br><span class="hljs-comment">//获取类文件中的所有方法，包括构造函数。</span><br>List&lt;MethodInfo&gt; list = classFile.getMethods();<br>Iterator&lt;MethodInfo&gt; it = list.iterator();<br><span class="hljs-keyword">while</span> (it.hasNext()) &#123;<br>    MethodInfo method = it.next();<br>    <span class="hljs-comment">// 获取方法的code表，其中有代码，和本地变量表等各种信息。</span><br>    CodeAttribute codeAttribute = (CodeAttribute) method.getAttribute(CodeAttribute.tag);<br>    <span class="hljs-comment">//localVariableAttribute 为提前声明的全局变量。</span><br>    <span class="hljs-comment">// 获取方法的本地变量表，如果没有使用javac -g 编译java文件，不会产生变量表</span><br>    localVariableAttribute = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);<br>    <span class="hljs-keyword">try</span> &#123;<br>        instrument(method); <span class="hljs-comment">// instrument 对方法进行字节码增强</span><br>    &#125; <span class="hljs-keyword">catch</span> (BadBytecode badBytecode <span class="hljs-comment">/*自定义异常*/</span>) &#123;<br>        badBytecode.printStackTrace();<br>    &#125;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<h2 id="定位实例生成的指令"><a href="#定位实例生成的指令" class="headerlink" title="定位实例生成的指令"></a>定位实例生成的指令</h2><p>实例的创建分为如下几类：</p>
<ul>
<li><p>类实例（即引用类型变量）</p>
<p>​    查找<code>invokespecial &lt;init&gt;</code></p>
<blockquote>
<p>​    因为实例的创建需要调用构造函数，所以我放弃了查找<code>new</code>指令，而是查找调用构造函数的指令<code>INVOKESPECIAL &lt;init&gt;</code>指令（其中&lt;init&gt;是<code>invokespecial</code>指令后的操作数，指构造函数）。</p>
<p>​    在实际字节码文件中，所有的函数都有各自的数字序号标签（存在常量池中），跟在invokespecial命令后的为函数的标签而非函数名。</p>
</blockquote>
</li>
<li><p>基本类型<strong>数组</strong></p>
<p>​    查找<code>newarray</code></p>
</li>
<li><p>引用类型<strong>数组</strong></p>
<p>​    查找<code>anewarray</code></p>
</li>
<li><p>多维<strong>数组</strong></p>
<p>​    查找<code>multianewarray</code></p>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// MethodInfo的getcodeAttribute函数可以拿到方法的字节码</span><br>CodeAttribute ca = method.getCodeAttribute();<br><span class="hljs-comment">// 通过迭代器可以遍历字节码指令。</span><br><span class="hljs-comment">// CodeIterator的迭代方式并不是一个字节一个字节迭代，而是一条指令一条指令地迭代。遍历下一个时，字节码指令和其后面的操作数会被当做一个项跳过</span><br>CodeIterator ci = ca.iterator();<br><br><span class="hljs-comment">// 注：在插桩之前需要对函数的最大操作栈深进行设置。</span><br><span class="hljs-comment">// 本次插桩需要插入函数调用，参数个数为3个，为了保证参数可以压入操作栈，需要将栈加深3层</span><br>ca.setMaxStack(ca.getMaxStack() + <span class="hljs-number">3</span>); <span class="hljs-comment">// To prevent insufficient stack depth.</span><br><span class="hljs-comment">// print method  bytecode</span><br><span class="hljs-keyword">while</span> (ci.hasNext()) &#123;<br>    <span class="hljs-comment">// index的数值为字节码的索引位置。</span><br>     <span class="hljs-keyword">int</span> index = ci.next(); <span class="hljs-comment">// the position of next opcode</span><br>    <span class="hljs-comment">// 变量op的数值为字节码的数值。</span><br>     <span class="hljs-keyword">int</span> op = ci.byteAt(index); <span class="hljs-comment">// get the value of opcode</span><br>    <span class="hljs-comment">//遍历字节码，找到需要的指令，然后进行插入。</span><br>    <span class="hljs-comment">//...</span><br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="类实例"><a href="#类实例" class="headerlink" title="类实例"></a>类实例</h3><p>​    一个实例的正常创建过程是这样的</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//首先new指令创建出实例引用，此时栈顶会有一个引用</span><br>0 new #3 &lt;T&gt;<br><span class="hljs-comment">// dup 指令会将栈顶再次压栈，此时栈顶有两个引用</span><br><span class="hljs-number">3</span> dup<br><span class="hljs-comment">// 调用该引用的构造函数，栈顶会弹出一个引用来调用函数，然后在构造函数内对实例进行一系列操作。</span><br>4 invokespecial #4 &lt;T.&lt;init&gt;&gt;<br><span class="hljs-comment">// 如果这个变量是本地变量，使用这个指令将栈顶的引用弹出并存储到本地变量表。存储在表的索引位置根据指令后的数字决定。</span><br><span class="hljs-number">7</span> astore_1<br><br><span class="hljs-comment">//java 代码如下</span><br>T t = <span class="hljs-keyword">new</span> T();<br><br></code></pre></td></tr></table></figure>

<p>我们需要做的是，在invokespecial之后插入几条命令，调用native函数，而在调用前我们需要在操作栈中设置好函数参数。</p>
<blockquote>
<p>注：在构造函数的第一句会调用父类构造函数，也会有<code>invokespecial &lt;init&gt;</code>指令，此时不需要再进行插桩。调用父类构造函数时需要使用<code>this</code>引用，所以在之前会调用<code>aload_0</code>将<code>this</code>引用入栈。</p>
<p>​    而<code>new</code>出来的实例一定会有<code>new</code>指令，所以需要在找到<code>invokespecial &lt;init&gt;</code>指令后进行判断，是否真的是创建的实例。</p>
</blockquote>
<h3 id="数组实例"><a href="#数组实例" class="headerlink" title="数组实例"></a>数组实例</h3><p>数组对象的创建并不像实例创建那么复杂，只需要设置好操作栈然后调用指令即可。不像类实例会出现其他的情况，关于数组实例的插桩直接找指令即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs java"> <span class="hljs-comment">// 创建高维数组之前调整操作栈</span><br> <span class="hljs-number">0</span> bipush <span class="hljs-number">10</span><br> <span class="hljs-number">2</span> bipush <span class="hljs-number">11</span><br> <span class="hljs-comment">// 调用指令创建，#6为类信息在常量池的编号，二维int型数组</span><br> 4 multianewarray #6 &lt;[[I&gt; dim 2<br> <span class="hljs-number">8</span> astore_2<br> <span class="hljs-number">9</span> bipush <span class="hljs-number">100</span><br><span class="hljs-comment">/*                   </span><br><span class="hljs-comment">Array Type	atype</span><br><span class="hljs-comment">T_BOOLEAN	4</span><br><span class="hljs-comment">T_CHAR		5</span><br><span class="hljs-comment">T_FLOAT		6</span><br><span class="hljs-comment">T_DOUBLE	7</span><br><span class="hljs-comment">T_BYTE		8</span><br><span class="hljs-comment">T_SHORT		9</span><br><span class="hljs-comment">T_INT		10</span><br><span class="hljs-comment">T_LONG		11</span><br><span class="hljs-comment">*/</span><br><span class="hljs-number">11</span> newarray <span class="hljs-number">10</span> (<span class="hljs-keyword">int</span>)<br><span class="hljs-number">13</span> astore_3<br><span class="hljs-comment">//java 代码如下              </span><br><span class="hljs-keyword">int</span>[][] a = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">10</span>][<span class="hljs-number">11</span>];<br><span class="hljs-keyword">int</span>[]b = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">100</span>];<br></code></pre></td></tr></table></figure>

<h2 id="插入代码"><a href="#插入代码" class="headerlink" title="插入代码"></a>插入代码</h2><p>因为需要插入的代码一致性很高，所以可以作为一个函数。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> ci 字节码迭代器</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> index INVOKESPECIAL NEWARRAY MULTIANEWARRAY ANEWARRAY 指令的索引</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> step index+step的位置为插入代码的位置</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> method 需要增强的方法</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> methodName 增强的方法的名称</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@throws</span> BadBytecode</span><br><span class="hljs-comment"> */</span><br><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">insertNativeC</span><span class="hljs-params">(CodeIterator ci, <span class="hljs-keyword">int</span> index, <span class="hljs-keyword">int</span> step, MethodInfo method, String methodName)</span> <span class="hljs-keyword">throws</span> BadBytecode </span>&#123;<br>    Bytecode bytecode = <span class="hljs-keyword">new</span> Bytecode(classFile.getConstPool());<br>    <span class="hljs-comment">// stackInObj函数 将引用入栈，如果是局部变量则返回在局部变量表中的位置，否则返回-1</span><br>    <span class="hljs-keyword">int</span> positionInLocalVariableTable = stackInObj(ci, index, step, bytecode);<br><br>    String objName;<br>    <span class="hljs-keyword">if</span> (positionInLocalVariableTable &gt; <span class="hljs-number">0</span> &amp;&amp; localVariableAttribute != <span class="hljs-keyword">null</span>) &#123;<br>        objName = localVariableAttribute.variableName(positionInLocalVariableTable);<br><br>    &#125; <span class="hljs-keyword">else</span> &#123;<br>        objName = <span class="hljs-string">&quot;withoutName&quot;</span>;<br>    &#125;<br>    <span class="hljs-comment">//压入bipush指令与操作数：代码行数</span><br>    bytecode.addOpcode(BIPUSH);<br>    bytecode.add(method.getLineNumber(index));<br>    <span class="hljs-comment">//压入ldc指令，指向变量名字符串</span><br>    bytecode.addLdc(objName);<br>    <span class="hljs-comment">//参数入栈完毕，插入函数调用</span><br>    bytecode.addInvokestatic(<span class="hljs-string">&quot;NativeC&quot;</span>, methodName, <span class="hljs-string">&quot;(Ljava/lang/Object;ILjava/lang/String;)V&quot;</span>);<br>    <span class="hljs-keyword">byte</span>[] bytes = bytecode.get();<br>    <span class="hljs-comment">//将bytecode中的缓存插入字节码中</span><br>    ci.insert(bytes);<br><br>&#125;<br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 将初始化的实例对象压入栈</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> ci</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> index</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> step</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> bytecode</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@throws</span> BadBytecode</span><br><span class="hljs-comment"> */</span><br><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">stackInObj</span><span class="hljs-params">(CodeIterator ci, <span class="hljs-keyword">int</span> index, <span class="hljs-keyword">int</span> step, Bytecode bytecode)</span> <span class="hljs-keyword">throws</span> BadBytecode </span>&#123;<br>    <span class="hljs-keyword">int</span> position = isAnonymousInit(ci, index, step);<br>    <span class="hljs-keyword">if</span> (position &gt;= <span class="hljs-number">0</span>) &#123;<br>        ci.next();<span class="hljs-comment">//skip astore</span><br>        <span class="hljs-comment">// 插入aload指令，根据局部变量表中的位置使用不同的指令</span><br>        bytecode.addAload(position);<br>        <span class="hljs-keyword">return</span> position;<br>    &#125; <span class="hljs-keyword">else</span> &#123;<br>        <span class="hljs-comment">// 如果是匿名对象，无法从本地变量表中找到引用，所以使用DUP指令，将栈顶的引用重复入栈。</span><br>        bytecode.addOpcode(Opcode.DUP);<br>        <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;	<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>
      </section>
      <section class="extra">
        
          <ul class="copyright">
  
    <li><strong>本文作者：</strong>Alex</li>
    <li><strong>本文链接：</strong><a href="https://alexande.gitee.io/2020/09/26/javassist2/index.html" title="https:&#x2F;&#x2F;alexande.gitee.io&#x2F;2020&#x2F;09&#x2F;26&#x2F;javassist2&#x2F;index.html">https:&#x2F;&#x2F;alexande.gitee.io&#x2F;2020&#x2F;09&#x2F;26&#x2F;javassist2&#x2F;index.html</a></li>
    <li><strong>版权声明：</strong>本博客所有文章均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" title="BY-NC-SA" target="_blank" rel="noopener">BY-NC-SA</a> 许可协议，转载请注明出处！</li>
  
</ul>
        
        
          <section class="donate">
  <div id="qrcode-donate">
    <img   class="lazyload" data-original="https://pic.izhaoo.com/alipay.jpg" src="" >
  </div>
  <div class="icon">
    <a href="javascript:;" id="alipay"><i class="iconfont iconalipay"></i></a>
    <a href="javascript:;" id="wechat"><i class="iconfont iconwechat-fill"></i></a>
  </div>
</section>
        
        
  <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/instrument/" rel="tag">instrument</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/java/" rel="tag">java</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/javassist/" rel="tag">javassist</a></li></ul> 

        
  <nav class="nav">
    <a href="/2020/11/07/Java-%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E5%85%A5%E9%97%A8/"><i class="iconfont iconleft"></i>Java 面向对象入门</a>
    <a href="/2020/09/24/javassist/">字节码增强（一）<i class="iconfont iconright"></i></a>
  </nav>

      </section>
      
    </section>
  </div>
</article></div>
      <div class="col-xl-3">
        
          
  <aside class="toc-wrap">
    <h3 class="toc-title">文章目录：</h3>
    <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%AF%BB%E5%8F%96%E7%B1%BB%E6%96%87%E4%BB%B6"><span class="toc-text">读取类文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96class%E7%9A%84%E6%96%B9%E6%B3%95%E8%A1%A8"><span class="toc-text">获取class的方法表</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AE%9A%E4%BD%8D%E5%AE%9E%E4%BE%8B%E7%94%9F%E6%88%90%E7%9A%84%E6%8C%87%E4%BB%A4"><span class="toc-text">定位实例生成的指令</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%B1%BB%E5%AE%9E%E4%BE%8B"><span class="toc-text">类实例</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%95%B0%E7%BB%84%E5%AE%9E%E4%BE%8B"><span class="toc-text">数组实例</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%8F%92%E5%85%A5%E4%BB%A3%E7%A0%81"><span class="toc-text">插入代码</span></a></li></ol>
  </aside>

        
      </div>
    </div>
  </div>
</main>
  

<footer class="footer">
  <div class="footer-social"><a 
        href="tencent://message/?Menu=yes&uin=272991962 "
        target="_blank"
        class="footer-social-item"
        onMouseOver="this.style.color= '#12B7F5'" 
        onMouseOut="this.style.color='#33333D'">
          <i class="iconfont  iconQQ "></i>
      </a><a 
        href="https://github.com/zheng-kai "
        target="_blank"
        class="footer-social-item"
        onMouseOver="this.style.color= '#9f7be1'" 
        onMouseOut="this.style.color='#33333D'">
          <i class="iconfont  icongithub-fill "></i>
      </a><a 
        href="https://gitee.com/AlexAnde "
        target="_blank"
        class="footer-social-item"
        onMouseOver="this.style.color= '#9f7be1'" 
        onMouseOut="this.style.color='#33333D'">
          <i class="iconfont  gitee-fill-round "></i>
      </a><a 
        href="mailto:272991962@qq.com "
        target="_blank"
        class="footer-social-item"
        onMouseOver="this.style.color=  '#12B7F5'" 
        onMouseOut="this.style.color='#33333D'">
          <i class="iconfont  iconmail "></i>
      </a></div>
  
    <div class="footer-copyright"><p>Powered by <a target="_blank" href="https://hexo.io">Hexo</a>  |  Theme - <a target="_blank" href="https://github.com/izhaoo/hexo-theme-zhaoo">zhaoo</a></p></div>
  
</footer>
  
      <div class="fab fab-plus">
    <i class="iconfont iconplus"></i>
  </div>
  
  
  <div class="fab fab-up">
    <i class="iconfont iconcaret-up"></i>
  </div>
  
  
    <div class="scrollbar j-scrollbar">
  <div class="scrollbar-current j-scrollbar-current"></div>
</div>
  
  
    
<script src="/js/color-mode.js"></script>

  
</body>

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>



  
<script src="https://cdn.bootcdn.net/ajax/libs/jquery.lazyload/1.9.1/jquery.lazyload.min.js"></script>




  
<script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js"></script>






  
<script src="https://cdn.bootcdn.net/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>




<script src="/js/utils.js"></script>
<script src="/js/script.js"></script>





  <script>
    (function () {
      var bp = document.createElement('script');
      var curProtocol = window.location.protocol.split(':')[0];
      if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
      } else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
      }
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
    })();
  </script>













</html>